/**
 * @file socket_server.cpp
 * @author fwy (2643660853@qq.com)
 * @brief 服务器套接字类实现
 * @version 0.1
 * @date 2025-08-17
 *
 * @copyright Copyright (c) 2025
 *
 */

#include "socket_server.h"
#include <cstring>

SocketServer::SocketServer()
{
    // 构造函数
}

SocketServer::~SocketServer()
{
    stop();
}

bool SocketServer::start(int port)
{
    if (server_fd_ != -1)
    {
        std::cerr << "Server already initialized" << std::endl;
        return false;
    }

    server_fd_ = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd_ == -1)
    {
        std::cerr << "Server socket creation failed" << std::endl;
        return false;
    }

    // 设置端口重用
    int opt = 1;
    if (setsockopt(server_fd_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
    {
        std::cerr << "Set socket option failed" << std::endl;
        stop();
        return false;
    }

    sockaddr_in server_addr{};
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    if (bind(server_fd_, (sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        std::cerr << "Bind failed" << std::endl;
        stop();
        return false;
    }

    if (listen(server_fd_, SOMAXCONN) < 0)
    {
        std::cerr << "Listen failed" << std::endl;
        stop();
        return false;
    }

    running_ = true;
    std::cout << "Server started on port " << port << std::endl;

    // 启动接受连接的线程
    accept_thread_ = std::thread(&SocketServer::acceptThread, this);

    return true;
}

bool SocketServer::sendMessage(const std::string &message, const std::string &client_id)
{
    if (!isRunning())
    {
        std::cerr << "Server not running" << std::endl;
        return false;
    }

    std::lock_guard<std::mutex> lock(client_mutex_);
    auto it = client_fds_.find(client_id);
    if (it != client_fds_.end())
    {
        if (send(it->second, message.c_str(), message.size(), 0) < 0)
        {
            std::cerr << "Failed to send message to " << client_id << std::endl;
            return false;
        }
        return true;
    }
    else
    {
        std::cerr << "Client " << client_id << " not found" << std::endl;
        return false;
    }
}

bool SocketServer::broadcastMessage(const std::string &message)
{
    if (!isRunning())
    {
        std::cerr << "Server not running" << std::endl;
        return false;
    }

    std::lock_guard<std::mutex> lock(client_mutex_);
    for (const auto &client : client_fds_)
    {
        if (send(client.second, message.c_str(), message.size(), 0) < 0)
        {
            std::cerr << "Failed to send message to " << client.first << std::endl;
        }
    }
    return true;
}

std::vector<std::string> SocketServer::getClientIds()
{
    std::vector<std::string> ids;
    std::lock_guard<std::mutex> lock(client_mutex_);
    for (const auto &client : client_fds_)
    {
        ids.push_back(client.first);
    }
    return ids;
}

bool SocketServer::disconnectClient(const std::string &client_id)
{
    std::lock_guard<std::mutex> lock(client_mutex_);
    auto it = client_fds_.find(client_id);
    if (it != client_fds_.end())
    {
        ::close(it->second);
        client_fds_.erase(it);
        std::cout << "Client disconnected: " << client_id << std::endl;
        if (client_disconnect_callback_)
        {
            client_disconnect_callback_(client_id);
        }
        return true;
    }
    return false;
}

void SocketServer::stop()
{
    running_ = false;

    // 关闭服务器套接字，会导致accept调用返回错误
    if (server_fd_ != -1)
    {
        ::close(server_fd_);
        server_fd_ = -1;
    }

    // 等待accept线程结束
    if (accept_thread_.joinable())
    {
        accept_thread_.join();
    }

    // 断开所有客户端连接
    {
        std::lock_guard<std::mutex> lock(client_mutex_);
        for (const auto &client : client_fds_)
        {
            ::close(client.second);
        }
        client_fds_.clear();
    }

    // 等待所有客户端线程结束
    for (auto &t : client_threads_)
    {
        if (t.joinable())
        {
            t.join();
        }
    }
    client_threads_.clear();
}

void SocketServer::acceptThread()
{
    while (running_ && server_fd_ != -1)
    {
        sockaddr_in client_addr{};
        socklen_t client_len = sizeof(client_addr);

        int new_client_fd = accept(server_fd_, (sockaddr *)&client_addr, &client_len);
        if (new_client_fd < 0)
        {
            if (running_)
            {
                std::cerr << "Accept failed" << std::endl;
            }
            continue;
        }

        std::string client_id = generateClientId(client_addr);

        {
            std::lock_guard<std::mutex> lock(client_mutex_);
            client_fds_[client_id] = new_client_fd;
        }

        std::cout << "New client connected: " << client_id << std::endl;

        if (client_connect_callback_)
        {
            client_connect_callback_(client_id);
        }

        // 创建新线程处理这个客户端
        client_threads_.push_back(std::thread(&SocketServer::handleClient, this, new_client_fd, client_id));
    }
}

void SocketServer::handleClient(int client_fd, const std::string &client_id)
{
    char buffer[1024];
    std::string real_client_id = client_id; // 默认使用连接ID

    // 心跳机制：记录最后一次心跳时间
    auto last_heartbeat = std::chrono::steady_clock::now();

    while (running_ && client_fd != -1)
    {
        // 设置超时时间为5秒
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(client_fd, &readfds);
        timeval tv;
        tv.tv_sec = 5;
        tv.tv_usec = 0;

        int ret = select(client_fd + 1, &readfds, nullptr, nullptr, &tv);
        if (ret > 0 && FD_ISSET(client_fd, &readfds))
        {
            ssize_t n = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
            if (n <= 0)
            {
                break;
            }
            buffer[n] = '\0';
            std::string message(buffer);

            // 检查是否是标识消息
            if (message.find("{\"type\":\"identity\"") == 0)
            {
                size_t pos_start = message.find("\"client_id\":\"");
                if (pos_start != std::string::npos)
                {
                    pos_start += 13;
                    size_t pos_end = message.find("\"", pos_start);
                    if (pos_end != std::string::npos)
                    {
                        std::string business_id = message.substr(pos_start, pos_end - pos_start);
                        {
                            std::lock_guard<std::mutex> lock(client_mutex_);
                            int fd = client_fds_[real_client_id];
                            client_fds_.erase(real_client_id);
                            client_fds_[business_id] = fd;
                            if (client_disconnect_callback_ && real_client_id != business_id)
                                client_disconnect_callback_(real_client_id);
                            real_client_id = business_id;
                            if (client_connect_callback_ && real_client_id != client_id)
                                client_connect_callback_(real_client_id);
                        }
                        std::cout << "Client " << client_id << " identified as: " << business_id << std::endl;
                        continue;
                    }
                }
            }

            // 心跳包检测
            if (message.find("{\"type\":\"ping\"") == 0)
            {
                last_heartbeat = std::chrono::steady_clock::now();
                continue;
            }

            // 非标识消息，交给回调处理
            if (message_callback_)
            {
                message_callback_(real_client_id, message);
            }
        }
        else if (ret == 0)
        {
            // select超时，检查心跳
            auto now = std::chrono::steady_clock::now();
            if (std::chrono::duration_cast<std::chrono::seconds>(now - last_heartbeat).count() > 15)
            {
                std::cerr << "Client " << real_client_id << " heartbeat timeout, disconnecting." << std::endl;
                break;
            }
            // 否则继续等待
        }
        else
        {
            // select错误
            break;
        }
    }

    // 客户端断开连接
    {
        std::lock_guard<std::mutex> lock(client_mutex_);
        auto it = client_fds_.find(real_client_id);
        if (it != client_fds_.end())
        {
            ::close(it->second);
            client_fds_.erase(it);

            if (client_disconnect_callback_)
            {
                client_disconnect_callback_(real_client_id);
            }
        }
    }

    std::cout << "Client disconnected: " << real_client_id << std::endl;
}

std::string SocketServer::generateClientId(const sockaddr_in &addr)
{
    char ip[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &addr.sin_addr, ip, sizeof(ip));
    return std::string(ip) + ":" + std::to_string(ntohs(addr.sin_port));
}